package com.ms.game.lobby;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ms.game.bank.BankAction;
import com.ms.game.gameActivity.GameActivityDAO;
import com.ms.game.gameActivity.db.GameActivitySettingModel;
import com.ms.game.invitefriend.InviteCodeAction;
import com.ms.game.lobby.bulletin.BulletinModelInfo;
import com.ms.game.lobby.db.LobbyGameListWhileDAO;
import com.ms.game.lobby.db.LobbyGameListWhileModel;
import com.ms.game.offlineSpin.message.OfflineSpinResultAction;
import com.ms.game.rebate.RebateAction;
import com.ms.game.sendgift.GiftPlayerData;
import com.ms.game.sendgift.SendGiftAction;
import com.ms.game.sendgift.SendGiftProcessor;
import com.ms.game.sendgift.db.SaveGiftRecordLogAsync;
import com.ms.game.sendgift.db.SendGiftRecordLog;
import com.ms.game.sendgift.message.SendGiftNotifyMessage;
import com.ms.game.sendgift.message.SendGiftResponse;
import com.ms.player.Player;
import com.ms.service.error.ErrorCode;
import com.ms.service.module.zone.db.GameHallDAO;
import com.ms.service.module.zone.module.BasicZoneModule;
import com.ms.service.telnet.STelnetCmd;
import com.xpec.c4.game.datamanager.BaseDataInfo;
import com.xpec.c4.game.datamanager.ResultNo;
import com.xpec.c4.game.datamanager.agent.moneyItem.MoneyItemChangeParam;
import com.xpec.c4.game.time.TimeSys;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.module.common.PlayerCommonInfoManager;

public class GameLobbyModule extends BasicZoneModule {

	@SuppressWarnings("unused")
	private static final Log log = LogFactory.getLog(GameLobbyModule.class);
	
	/** game lobby 資料管理 */
	private GameLobbyProcesser gameLobby = new GameLobbyProcesser();

	
	private GameListWhileGroup whileGroup = new GameListWhileGroup();
	
	private HashMap<Integer, BulletinModelInfo> BulletinMap = new HashMap<Integer, BulletinModelInfo>(); 

	public GameLobbyModule() {
		setZone(gameLobby);
	}

	@Override
	public boolean startup() {
		return super.startup();
	}

	@Override
	public void shutdown() {
		super.shutdown();
	}

	@Override
	public void init() {
		super.init();

		autoInsertNewGameTypeToDB();
		cacheGameTypeData();
		cacheBulletinList();
		
		registerActionClass(GameLobbyAction.class);
		registerActionClass(SendGiftAction.class);
		registerActionClass(BankAction.class);
		registerActionClass(RebateAction.class);
		registerActionClass(OfflineSpinResultAction.class);
		registerActionClass(InviteCodeAction.class);
	}
	
	@Override
	public void onModuleServerReadyStart()
	{
		super.onModuleServerReadyStart();
		
		//撈取玩家遊戲白名單資料
		initWhileGroup();
		
		initGameActivitySettings();
		
	}
	
	private void initGameActivitySettings(){
		ArrayList<GameActivitySettingModel> gameActivitySettings = GameActivityDAO.loadGameActivitySetting(null);
		gameLobby.onLoadActivitySetting(gameActivitySettings);
	}
	

	@Override
	public void procTelnetCommand(STelnetCmd obj) {
		super.procTelnetCommand(obj);
	}

	public GameLobbyProcesser getGameLobby() {
		return gameLobby;
	}

	public void setGameLobby(GameLobbyProcesser gameLobby) {
		this.gameLobby = gameLobby;
	}
	
	/**
	 * 暫存大廳遊戲館資料
	 * 2015/7/30 add by robert
	 */
	private void cacheGameTypeData()
	{
		gameLobby.onCacheGameTypeData(null);
	}
	
	public GameListWhileGroup getWhileGroup() {
		return whileGroup;
	}

	public void setWhileGroup(GameListWhileGroup whileGroup) {
		this.whileGroup = whileGroup;
	}
	
	
	
	public void sendGiftTakenCallBack(BaseDataInfo obj, Object... userObject){
		int messageType = (int)userObject[0];
		GiftPlayerData data = (GiftPlayerData)userObject[1];
		if(obj.getResultCode() == ResultNo.OK){
			data.response.errorCode = ErrorCode.SUCCESS;
		}else{
			data.response.errorCode = obj.getResultCode();
		}
		MessageAction.sendMessage(data.sessionID, messageType, data.response);
	}
	
	
	
	/**
	 * 送禮物，將物品保留在server上
	 * @see com.ms.game.sendgift.db.LoadSendGiftPlayerDataAsync#execute
	 */
	@SuppressWarnings("unchecked")
	public void sendGiftFirstCallBack(BaseDataInfo obj, Object... userObject){
		//更新zone上的角色資訊，會自己判斷是否成功才更改
		int messageType = (int)userObject[0];
		GUID sessionID = (GUID)userObject[1];
		long charge = (long)userObject[2];
		HashMap<String , Integer> items = (HashMap<String , Integer>)userObject[3];
		Player playerData = (Player)userObject[4];
		Player targetData = (Player)userObject[5];
		long sendOrderId = (Long)userObject[6];
		String orderNum = (String)userObject[7];

		MoneyItemChangeParam param = (MoneyItemChangeParam) obj.getData();
		SendGiftProcessor.OnSendGiftFirstStepCallBack(messageType, sessionID, playerData, targetData, charge, items, this, param, sendOrderId, orderNum, false);
	}
	
	/**
	 * 寄送禮物退錢或送錢
	 * @see com.ms.game.sendgift.db.SaveGiftNotifyAnswerAsync
	 */
	public void sendGiftCallBack(BaseDataInfo obj, Object... userObject){
		
		SendGiftRecordLog logModel = (SendGiftRecordLog)userObject[3];
		
		if(obj.getResultCode() == ResultNo.OK){
			logModel.setErrorCode(ErrorCode.SUCCESS);
			int messageType = (int)userObject[0];
			SendGiftNotifyMessage message = (SendGiftNotifyMessage)userObject[1];
			GUID targetGUID = (GUID)userObject[2];

			
			GUID targetSession = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(targetGUID);
			if(targetSession != null){
				//在線上發送
				MessageAction.sendMessage(targetSession, messageType, message);
			}
		}
		else{
			MoneyItemChangeParam param = (MoneyItemChangeParam) obj.getData();
			logModel.setErrorCode(param.getResult());
		}
		
		//寫log
		SaveGiftRecordLogAsync saveLog = new SaveGiftRecordLogAsync();
		saveLog.logModel = logModel;
		addAsyncCommand(saveLog);
	}
	
	/**
	 * 寄送禮物退錢或送錢
	 * @see 
	 */
	public void sendGiftCallBackFinial(BaseDataInfo obj, Object... userObject){
		
		GUID playerID = (GUID)userObject[0];
		SendGiftResponse response = (SendGiftResponse)userObject[1];
		GUID targetGUID = (GUID)userObject[2];
		SendGiftNotifyMessage notify = (SendGiftNotifyMessage)userObject[3];
		SendGiftRecordLog logModel = (SendGiftRecordLog)userObject[4];
		
		GUID playerSession = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(playerID);
		GUID targetSession = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(targetGUID);
		
		response.createTime = logModel.getCreateTime().getTime();
		notify.createTime = logModel.getCreateTime().getTime();
		
		if(obj.getResultCode() == ResultNo.OK){
			logModel.setErrorCode(ErrorCode.SUCCESS);
			if(playerSession != null){
				//在線上發送
				response.errorCode = ErrorCode.SUCCESS;
				MessageAction.sendMessage(playerSession, MessageTypes.S_GIFT_FINIAL_GIVE_RESPONSE, response);
			}
				
			if(targetSession != null){
				//在線上發送
				MessageAction.sendMessage(targetSession, MessageTypes.S_GIFT_FINIAL_RETURN_RESPONSE, notify);
			}
			
		}else{
			MoneyItemChangeParam param = (MoneyItemChangeParam) obj.getData();
			logModel.setErrorCode(param.getResult());
			if(playerSession != null){
				//在線上發送
				response.errorCode = param.getResult();
				MessageAction.sendMessage(playerSession, MessageTypes.S_GIFT_FINIAL_GIVE_RESPONSE, response);
			}
				
			if(targetSession != null){
				//在線上發送
				MessageAction.sendMessage(targetSession, MessageTypes.S_GIFT_FINIAL_RETURN_RESPONSE, notify);
			}
		}
		//寫log
		SaveGiftRecordLogAsync saveLog = new SaveGiftRecordLogAsync();
		saveLog.logModel = logModel;
		addAsyncCommand(saveLog);
	}
	
	
	/**
	 * 寄送禮物退錢或送錢
	 * @see com.ms.game.sendgift.SendGiftProcessor#OnSendGiftCancelFirstStepCallBack
	 */
	public void sendGiftCallBackCancel(BaseDataInfo obj, Object... userObject){
		
		GUID playerID = (GUID)userObject[0];
		GUID targetGUID = (GUID)userObject[1];
		SendGiftResponse response = (SendGiftResponse)userObject[2];
		SendGiftNotifyMessage notify = (SendGiftNotifyMessage)userObject[3];
		
		GUID playerSession = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(playerID);
		GUID targetSession = PlayerCommonInfoManager.getInstance().getSessionByPlayerGuid(targetGUID);
		
		if(obj.getResultCode() == ResultNo.OK){
			if(playerSession != null){
				//在線上發送
				response.errorCode = ErrorCode.SUCCESS;
				MessageAction.sendMessage(playerSession, MessageTypes.S_GIFT_FIRST_CANCEL_RESPONSE, response);
			}
				
			if(targetSession != null){
				//在線上發送
				MessageAction.sendMessage(targetSession, MessageTypes.S_GIFT_FIRST_CANCEL_RETURN_RESPONSE, notify);
			}
			
		}else{
			MoneyItemChangeParam param = (MoneyItemChangeParam) obj.getData();
			if(playerSession != null){
				//在線上發送
				response.errorCode = param.getResult();
				MessageAction.sendMessage(playerSession, MessageTypes.S_GIFT_FIRST_CANCEL_RESPONSE, response);
			}
				
			if(targetSession != null){
				//在線上發送
				MessageAction.sendMessage(targetSession, MessageTypes.S_GIFT_FIRST_CANCEL_RETURN_RESPONSE, notify);
			}
		}
	}
	
	/**
	 * 初始化遊戲列表白名單
	 */
	public void initWhileGroup()
	{
		long nowtime = TimeSys.currentTimeMills();
		List<LobbyGameListWhileModel> list =LobbyGameListWhileDAO.getAll();
		
		ConcurrentHashMap<String, GameListWhileData> group = whileGroup.getGroup();
		for(LobbyGameListWhileModel mm:list)
		{
			if(mm.isDeny())
			{
				continue;
			}
			
			
			//是否過期?
			if( mm.getExpired()!=0 && mm.getExpired() < nowtime)
			{
				continue;
			}
			
			
			ArrayList<String> wgame =whileGroup.strToList(mm.getAllowlist());
			ArrayList<String> wicon = whileGroup.strToList(mm.getAllowicons());
			
			GameListWhileData data = new GameListWhileData();
			data.playerid = mm.getPlayerid();
			data.expiredtime = mm.getExpired();
			data.list = wgame;
			data.iconlist = wicon;
			group.put(data.playerid, data);
		}
		
		if(log.isInfoEnabled())
		{
			log.info(group.toString());
		}
		
	}

	public HashMap<Integer, BulletinModelInfo> getBulletinMap() {
		return BulletinMap;
	}

	public void setBulletinMap(HashMap<Integer, BulletinModelInfo> bulletinMap) {
		BulletinMap = bulletinMap;
	}

	public void cacheBulletinList(){
		gameLobby.updateBulletinList(this);
	}
	
	/**
	 * 參考GameType與OSType自動新增遊戲館
	 */
	public void autoInsertNewGameTypeToDB(){
		//如果自己是第一個module就可以做
		if(this.isFirstModule()){
			GameHallDAO.checkAndInsertNewGameTypeModel();
		}
	}
}
